/**
 * 工具函数测试
 */

import { describe, it, expect } from 'vitest'
import {
  cn,
  formatDateTime,
  formatRelativeTime,
  formatDuration,
  formatFileSize,
  formatNumber,
  formatPercentage,
  truncateString,
  capitalize,
  camelToKebab,
  kebabToCamel,
  uniqueArray,
  groupBy,
  sortBy,
  deepClone,
  parseQueryParams,
  buildQueryString,
  isValidEmail,
  isValidUrl,
  isValidJson,
  debounce,
  throttle,
} from '@/lib/utils'

describe('样式工具函数', () => {
  it('cn 应该正确合并类名', () => {
    expect(cn('class1', 'class2')).toBe('class1 class2')
    expect(cn('class1', undefined, 'class2')).toBe('class1 class2')
    expect(cn('bg-red-500', 'bg-blue-500')).toBe('bg-blue-500')
  })
})

describe('时间格式化工具', () => {
  const testDate = new Date('2024-01-15T10:30:00Z')

  it('formatDateTime 应该正确格式化日期时间', () => {
    const result = formatDateTime(testDate, 'yyyy-MM-dd')
    expect(result).toBe('2024-01-15')
  })

  it('formatDuration 应该正确格式化时长', () => {
    expect(formatDuration(500)).toBe('500ms')
    expect(formatDuration(1500)).toBe('1s')
    expect(formatDuration(65000)).toBe('1m 5s')
    expect(formatDuration(3665000)).toBe('1h 1m')
  })
})

describe('数据格式化工具', () => {
  it('formatFileSize 应该正确格式化文件大小', () => {
    expect(formatFileSize(0)).toBe('0 B')
    expect(formatFileSize(1024)).toBe('1 KB')
    expect(formatFileSize(1048576)).toBe('1 MB')
    expect(formatFileSize(1073741824)).toBe('1 GB')
  })

  it('formatNumber 应该正确格式化数字', () => {
    expect(formatNumber(1234)).toBe('1,234')
    expect(formatNumber(1234.56, 2)).toBe('1,234.56')
  })

  it('formatPercentage 应该正确格式化百分比', () => {
    expect(formatPercentage(0.1234)).toBe('12.3%')
    expect(formatPercentage(0.1234, 2)).toBe('12.34%')
  })
})

describe('字符串工具函数', () => {
  it('truncateString 应该正确截断字符串', () => {
    expect(truncateString('hello world', 5)).toBe('he...')
    expect(truncateString('hello', 10)).toBe('hello')
  })

  it('capitalize 应该正确首字母大写', () => {
    expect(capitalize('hello')).toBe('Hello')
    expect(capitalize('HELLO')).toBe('HELLO')
  })

  it('camelToKebab 应该正确转换驼峰命名', () => {
    expect(camelToKebab('helloWorld')).toBe('hello-world')
    expect(camelToKebab('XMLHttpRequest')).toBe('xml-http-request')
  })

  it('kebabToCamel 应该正确转换短横线命名', () => {
    expect(kebabToCamel('hello-world')).toBe('helloWorld')
    expect(kebabToCamel('xml-http-request')).toBe('xmlHttpRequest')
  })
})

describe('数组工具函数', () => {
  it('uniqueArray 应该正确去重', () => {
    expect(uniqueArray([1, 2, 2, 3])).toEqual([1, 2, 3])
    
    const objects = [
      { id: 1, name: 'a' },
      { id: 2, name: 'b' },
      { id: 1, name: 'c' }
    ]
    expect(uniqueArray(objects, 'id')).toEqual([
      { id: 1, name: 'a' },
      { id: 2, name: 'b' }
    ])
  })

  it('groupBy 应该正确分组', () => {
    const data = [
      { type: 'a', value: 1 },
      { type: 'b', value: 2 },
      { type: 'a', value: 3 }
    ]
    
    const result = groupBy(data, 'type')
    expect(result).toEqual({
      a: [{ type: 'a', value: 1 }, { type: 'a', value: 3 }],
      b: [{ type: 'b', value: 2 }]
    })
  })

  it('sortBy 应该正确排序', () => {
    const data = [
      { name: 'c', value: 3 },
      { name: 'a', value: 1 },
      { name: 'b', value: 2 }
    ]
    
    const result = sortBy(data, 'name')
    expect(result[0].name).toBe('a')
    expect(result[1].name).toBe('b')
    expect(result[2].name).toBe('c')
  })
})

describe('对象工具函数', () => {
  it('deepClone 应该正确深度克隆', () => {
    const original = {
      a: 1,
      b: {
        c: 2,
        d: [3, 4]
      }
    }
    
    const cloned = deepClone(original)
    expect(cloned).toEqual(original)
    expect(cloned).not.toBe(original)
    expect(cloned.b).not.toBe(original.b)
    expect(cloned.b.d).not.toBe(original.b.d)
  })
})

describe('URL工具函数', () => {
  it('parseQueryParams 应该正确解析查询参数', () => {
    const result = parseQueryParams('?a=1&b=2&c=hello%20world')
    expect(result).toEqual({
      a: '1',
      b: '2',
      c: 'hello world'
    })
  })

  it('buildQueryString 应该正确构建查询字符串', () => {
    const params = { a: 1, b: 'hello world', c: undefined }
    const result = buildQueryString(params)
    expect(result).toBe('a=1&b=hello+world')
  })
})

describe('验证工具函数', () => {
  it('isValidEmail 应该正确验证邮箱', () => {
    expect(isValidEmail('test@example.com')).toBe(true)
    expect(isValidEmail('invalid-email')).toBe(false)
    expect(isValidEmail('test@')).toBe(false)
  })

  it('isValidUrl 应该正确验证URL', () => {
    expect(isValidUrl('https://example.com')).toBe(true)
    expect(isValidUrl('http://localhost:3000')).toBe(true)
    expect(isValidUrl('invalid-url')).toBe(false)
  })

  it('isValidJson 应该正确验证JSON', () => {
    expect(isValidJson('{"a": 1}')).toBe(true)
    expect(isValidJson('[1, 2, 3]')).toBe(true)
    expect(isValidJson('invalid json')).toBe(false)
  })
})

describe('防抖和节流', () => {
  it('debounce 应该正确防抖', async () => {
    let count = 0
    const fn = debounce(() => count++, 100)
    
    fn()
    fn()
    fn()
    
    expect(count).toBe(0)
    
    await new Promise(resolve => setTimeout(resolve, 150))
    expect(count).toBe(1)
  })

  it('throttle 应该正确节流', async () => {
    let count = 0
    const fn = throttle(() => count++, 100)
    
    fn()
    fn()
    fn()
    
    expect(count).toBe(1)
    
    await new Promise(resolve => setTimeout(resolve, 150))
    fn()
    expect(count).toBe(2)
  })
})
